package service

import (
	"context"
	"fmt"
	"time"

	"task/config"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

var (
	requestTotal = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Name: fmt.Sprintf("%s_request_total", config.Conf.TaskDispatch.Name),
			Help: "Number of task dispatch requests",
		},
		[]string{"method", "grpc_code"},
	)
	requestDuration = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Name: fmt.Sprintf("%s_request_duration", config.Conf.TaskDispatch.Name),
			Help: "Duration of task dispatch requests",
		},
		[]string{"method", "grpc_code"},
	)
	requestLatency = promauto.NewSummaryVec(
		prometheus.SummaryOpts{
			Name:       fmt.Sprintf("%s_request_latency", config.Conf.TaskDispatch.Name),
			Help:       "Task dispatch request latency",
			Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
		},
		[]string{"method", "grpc_code"},
	)
)

// DispatchUnaryServerInterceptor dispatch unary server interceptor.
func DispatchUnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
	start := time.Now()
	defer func() {
		grpcCode := codes.OK.String()
		if err != nil {
			grpcCode = codes.Internal.String()
		}
		duration := float64(time.Since(start) / time.Millisecond)
		requestTotal.With(prometheus.Labels{
			"method":    info.FullMethod,
			"grpc_code": grpcCode,
		}).Inc()
		requestDuration.With(prometheus.Labels{
			"method":    info.FullMethod,
			"grpc_code": grpcCode,
		}).Add(duration)
		requestLatency.With(prometheus.Labels{
			"method":    info.FullMethod,
			"grpc_code": grpcCode,
		}).Observe(duration)
	}()
	resp, err = handler(ctx, req)
	return
}
